﻿using System;
using System.Collections;
using System.Collections.Generic;
using System.IO;
using System.Net;
using System.Threading;
using System.Xml;

using UnityEngine;
using UnityEngine.UI;
/// <summary>
/// 更新面板
/// </summary>
public class UpdatePanel : PanelBase
{
    public Slider slider;
    public Text t1;
    public Text t2;
    public Text t3;
    public Text t4;

    /// <summary>
    /// http://211.159.159.200/AB/
    /// </summary>
    string serverRoot = "http://211.159.159.200/AB/";
    /// <summary>
    /// 服务器端版本文件地址
    /// </summary>
    string serverVerUrl;

    string abRoot;
    /// <summary>
    /// ab文件存放路径
    /// </summary>
    static string abPath;

    Thread t;

    int dyet = 0;
    /// <summary>
    /// 更新文件的队列
    /// </summary>
    Queue<Content> upContent = new Queue<Content>();

    // Use this for initialization
    void Start()
    {
        abPath = Application.persistentDataPath + "/AB/";
        if (!Directory.Exists(abPath))
        {
            Directory.CreateDirectory(abPath);
        }

        serverVerUrl = serverRoot +GetPlatformName(Application.platform) + "/VersionMD5.txt";
        abRoot = serverRoot + GetPlatformName(Application.platform)+"/";
         
        StartCoroutine(DownLoadVersion());
    }

    /// <summary>
    /// 获取平台名
    /// </summary>
    /// <returns>The platform name.</returns>
    /// <param name="rp">Rp.</param>
    public string GetPlatformName(RuntimePlatform rp)
    {
        switch (rp)
        {
            case RuntimePlatform.Android:
                return rp.ToString();
            case RuntimePlatform.IPhonePlayer:
                return "iOS";
            case RuntimePlatform.WindowsEditor:
            case RuntimePlatform.WindowsPlayer:
                return "Windows";
            case RuntimePlatform.OSXEditor:
            case RuntimePlatform.OSXPlayer:
                return "OSX";
            default:
                Debug.LogError("不支持的平台");
                return "";
        }
    }


    public override void Init(params object[] args)
    {
        base.Init(args);
        layer = PanelLayer.Panel;
    }

    public override void OnShowing()
    {
        base.OnShowed();
        slider = panelObj.transform.Find("Slider").GetComponent<Slider>();
        t1 = panelObj.transform.Find("t1").GetComponent<Text>();
        t2 = panelObj.transform.Find("t2").GetComponent<Text>();
        t3 = panelObj.transform.Find("t3").GetComponent<Text>();
        t4 = panelObj.transform.Find("t4").GetComponent<Text>();
    }

    /// <summary>
    /// 服务器端版本信息
    /// </summary>
    VerInfo serverVerInfo;

    IEnumerator DownLoadVersion()
    {
        WWW www = new WWW(serverVerUrl);
        Debug.Log("serverVerUrl:" + serverVerUrl);
        yield return www;
        Debug.Log("www.text:"+ www.text);

        if (File.Exists(abPath + "VersionMD5-new.txt"))
        {
            File.Delete(abPath + "VersionMD5-new.txt");
        }
        FileStream fs = new FileStream(abPath + "VersionMD5-new.txt", FileMode.Create);
        //获得字节数组
        byte[] data = System.Text.Encoding.Default.GetBytes(www.text);
        //开始写入
        fs.Write(data, 0, data.Length);
        //清空缓冲区、关闭流
        fs.Flush();
        fs.Close();

        serverVerInfo = ReadMD5File(abPath + "VersionMD5-new.txt");
        Debug.Log(serverVerInfo.version);

        //本地有版本文件
        if (File.Exists(abPath + "VersionMD5.txt"))
        {
            VerInfo localVerInfo = ReadMD5File(abPath + "VersionMD5.txt");
            //服务器版本号高于本地版本号
            if (serverVerInfo.version >= localVerInfo.version)
            {
                VerInfo upInfo = GetUpInfo(serverVerInfo, localVerInfo);
                foreach (Content content in upInfo.content)
                {
                    upContent.Enqueue(content);
                }
            } 
        }
        //本地没有版本文件
        else
        {
            foreach (Content c in serverVerInfo.content)
            {
                upContent.Enqueue(c);
            }
        }

        if (upContent.Count > 0)
        {
            StartDownLoad();
        }
        else
        {
            ResMgr.mode = RESMODE.AB; 
            PanelMgr.Instance.OpenPanel<LoginPanel>("");
            Close();
        }
    }

    void StartDownLoad()
    {
        start = true;
    }

    bool start = false;
    bool isRun = false; 

    public override void Update()
    {
        t1.text = s1;
        t2.text = s2;
        t3.text = s3;
        t4.text = s4;
        slider.value = progress;

        if (start && !isRun && upContent.Count > 0)
        {
            Debug.Log("upContent.Count " + upContent.Count);
            isRun = true;
            Content content = upContent.Dequeue();
            Debug.Log("Here  " + content.name);
            content.url = abRoot + content.name;
            Debug.Log("content.url  " + content.url);
            content.filePath = abPath + content.name; 
            content.cb += Test;

            if (t != null)
            {
                if (t.IsAlive)
                {
                    t.Abort();
                    t = null;
                }
            }

            t = new Thread(new ParameterizedThreadStart(DownLoad));
            t.Start(content);
        }
    }

    /// <summary>
    /// 比较版本信息
    /// </summary>
    /// <param name="serVer"></param>
    /// <param name="localVer"></param>
    /// <returns></returns>
    public  VerInfo GetUpInfo(VerInfo serVer, VerInfo localVer)
    {
        VerInfo upInfo = new VerInfo();
        upInfo.content = new List<Content>();
        foreach (Content content in serVer.content)
        {
            if (!localVer.content.Contains(content)||!File.Exists(abPath + content.name))
            {
                Debug.Log(abRoot + content.name);
                upInfo.content.Add(content);
            }
        }

        return upInfo;
    }

    public static VerInfo ReadMD5File(string fileName)
    {
        VerInfo versionInfo = new VerInfo();
        versionInfo.content = new List<Content>();
        versionInfo.version = 0;
        // 如果文件不存在，则直接返回
        if (File.Exists(fileName) == false)
        {
            return versionInfo;
        }

        try
        {
            XmlDocument XmlDoc = new XmlDocument();
            XmlDoc.Load(fileName);
            XmlElement XmlRoot = XmlDoc.DocumentElement;

            foreach (XmlNode node in XmlRoot.ChildNodes)
            {
                //Debug.Log("node.Name:" + node.Name);
                if (node.Name == "File")
                {
                    if ((node is XmlElement) == false)
                    {
                        continue;
                    }
                    Content ui = new Content();
                    ui.name = (node as XmlElement).GetAttribute("name");
                    ui.md5 = (node as XmlElement).GetAttribute("md5");
                    versionInfo.content.Add(ui);
                }
                else
                {
                    versionInfo.version = Convert.ToInt32((node as XmlElement).GetAttribute("code"));
                }
            }

            XmlRoot = null;
            XmlDoc = null;
        }
        catch(Exception e)
        {
            Debug.LogError(e.ToString());
        }
        return versionInfo;
    }

    /// <summary>
    /// 更新的版本信息
    /// </summary>
    public struct VerInfo
    {
        public int version;
        public List<Content> content;
    }

    /// <summary>
    /// 更新内容信息
    /// </summary>
    public struct Content
    {
        /// <summary>
        /// 文件的url下载地址
        /// </summary>
        public string url;

        /// <summary>
        /// 文件名
        /// </summary>
        public string name;

        /// <summary>
        /// 文件的保存路径
        /// </summary>
        public string filePath;

        /// <summary>
        /// 文件的md5
        /// </summary>
        public string md5;

        /// <summary>
        /// 下载回调
        /// </summary>
        public CallBack cb;
       
    }

    private void OnApplicationQuit()
    {
        if (t != null)
        {
            if (t.IsAlive)
            {
                t.Abort();
                t = null;
            }
        }
    }
    /// <summary>
    /// 下载委托
    /// </summary>
    /// <param name="di"></param>
    public delegate void CallBack(OutInfo di);
    public CallBack dp;

    string s1 = "";
    string s2 = "";
    string s3 = "";
    string s4 = "";
    float progress = 0;

    void Test(OutInfo di)
    {
        s1 = "大小：" + di.TotalBytesToReceive / 1024 + " kb";
        s2 = "已下载：" + di.BytesReceived / 1024 + " kb";

        progress = (float)di.BytesReceived / di.TotalBytesToReceive;

        s3 = "进度：" + (progress * 100).ToString("00") + "%";
        s4 = upContent.Count + " 个文件需要更新";
        if (progress == 1)
        {
            //Debug.Log("isRun = false");
        }
    }

    /// <summary> 
    /// 断点下载 
    /// </summary>
    /// <param name="ps"></param>
    void DownLoad(object ps)
    {
        Content content = (Content)ps;
        OutInfo oi = new OutInfo();
        string uri = content.url;
        //Debug.Log(uri);
        string saveFile = content.filePath;
        //Debug.Log(saveFile);
        CallBack cd = content.cb;
        //打开网络连接
        HttpWebRequest request = (System.Net.HttpWebRequest)System.Net.HttpWebRequest.Create(uri);
        HttpWebRequest requestGetCount = (System.Net.HttpWebRequest)System.Net.HttpWebRequest.Create(uri);
        //文件总长度
        long serverLength = requestGetCount.GetResponse().ContentLength;
        oi.TotalBytesToReceive = serverLength;

        //本地文件的长度
        long localLen = 0;
        FileStream fs;
        if (File.Exists(saveFile))
        {
            fs = File.OpenWrite(saveFile);
            localLen = fs.Length;
            //已经下载完
            if (serverLength - localLen <= 0)
            {
                fs.Close();
                oi.BytesReceived = localLen;

                cd(oi);

                CheckeFile(content);

                isRun = false;

                request.Abort();
                request = null;
                requestGetCount.Abort();
                requestGetCount = null;

                return;
            }
            else
            {
                oi.BytesReceived = localLen;
                //移动文件流中的当前指针
                fs.Seek(localLen, SeekOrigin.Current);
            }
        }
        else
        {
            fs = new FileStream(saveFile, FileMode.Create);
        }

        if (localLen > 0)
        {
            //设置Range值
            request.AddRange((int)localLen);
        }

        //向服务器请求，获得服务器回应数据流
        Stream st = request.GetResponse().GetResponseStream();
        int len = 1024 * 8;

        byte[] nbytes = new byte[len];
        int nReadSize = 0;
        nReadSize = st.Read(nbytes, 0, len);
        while (nReadSize > 0)
        {
            fs.Write(nbytes, 0, nReadSize);
            nReadSize = st.Read(nbytes, 0, len);
            oi.BytesReceived = fs.Length;
            cd(oi);
        }

        oi.BytesReceived = fs.Length;
        cd(oi);

        st.Close();
        fs.Close();

        CheckeFile(content);

        request.Abort();
        request = null;
        requestGetCount.Abort();
        requestGetCount = null;
        //这里放更新安装代码,或者可以测试这个下载的包有没有出错,验证sha和md5
        isRun = false;
    }

    /// <summary>
    /// 检查文件完整性
    /// </summary>
    void CheckeFile(Content content)
    {
        if (Util.GetFileMD5(abPath + content.name) == content.md5)
        {
            Debug.Log("md5 ok");
            if (upContent.Count < 1)
            {
                Debug.Log("更新完成！");
                //本地有版本文件
                if (File.Exists(abPath + "VersionMD5.txt"))
                {
                    File.Delete(abPath + "VersionMD5.txt");
                }

                File.Copy(abPath + "VersionMD5-new.txt", abPath + "VersionMD5.txt");
                File.Delete(abPath + "VersionMD5-new.txt");

                MsgMgr.Instance.AddListener("UpdateComplete", UpdateComplete);
                MsgMgr.Instance.SendMsg("UpdateComplete", null);
                 
            }
        }
        else
        {
            File.Delete(abPath + content.name);
            Debug.Log("md5 error 重新加入下载队列");
            upContent.Enqueue(content);
        }
    }
    
    void UpdateComplete(object [] args)
    {
        MsgMgr.Instance.RemoveListener("UpdateComplete", UpdateComplete);
        Loom.QueueOnMainThread(() =>
        {
            PanelMgr.Instance.OpenPanel<LoginPanel>("");
            Close();
        });
        
    }

    /// <summary>
    /// 下载输出信息
    /// </summary>
    public struct OutInfo
    {
        /// <summary>
        /// 总长度
        /// </summary>
        public long TotalBytesToReceive;
        /// <summary>
        /// 已接收的字节数
        /// </summary>
        public long BytesReceived;
    }
}
